/**
 * 文件名: condition_variable_any_usage_test.cpp
 *
 * 构建:
 *   g++ -std=c++20 -pthread condition_variable_any_usage_test.cpp \
 *       -lgtest -lgtest_main -o condition_variable_any_usage_test
 * 运行:
 *   ./condition_variable_any_usage_test
 *
 * 示例涵盖：
 *   1. 基础用法：shared_mutex + condition_variable_any。
 *   2. 超时等待：wait_for 演示虚假唤醒与谓词的重要性。
 *   3. 任务队列：使用 shared_mutex 构建读多写少的任务缓存。
 *   4. 自定义锁适配：展示 condition_variable_any 支持手写 BasicLockable。
 */

#include <gtest/gtest.h>

#include <condition_variable>
#include <mutex>
#include <queue>
#include <shared_mutex>
#include <thread>

using namespace std::chrono_literals;

//------------------------------------------------------------------------------
// 1) 基础用法：在 shared_mutex 上等待状态改变。
//------------------------------------------------------------------------------
TEST(ConditionVariableAnyUsageTest, WorksWithSharedMutex) {
    std::shared_mutex sm;                // 读写锁
    std::condition_variable_any cv;      // 支持任意 BasicLockable
    bool ready = false;

    std::thread setter([&] {
        std::this_thread::sleep_for(5ms);            // 模拟耗时
        std::unique_lock lock(sm);                   // 独占写锁
        ready = true;                                // 更新条件
        cv.notify_all();                             // 唤醒等待者
    });

    std::unique_lock lock(sm);                       // 获得写锁才能 wait
    cv.wait(lock, [&] { return ready; });            // 谓词防止虚假唤醒
    lock.unlock();

    setter.join();
    EXPECT_TRUE(ready);
}

//------------------------------------------------------------------------------
// 2) 超时等待：演示 wait_for、虚假唤醒，以及通知顺序。
//------------------------------------------------------------------------------
TEST(ConditionVariableAnyUsageTest, WaitForTimeoutAndNotify) {
    std::condition_variable_any cv;
    std::timed_mutex timedMutex;    // 支持 lock / unlock / try_lock_for
    bool dataReady = false;
    bool workerEntered = false;

    std::thread producer([&] {
        std::this_thread::sleep_for(15ms);
        std::unique_lock lock(timedMutex);
        dataReady = true;
        cv.notify_one();            // 先改状态后通知
    });

    std::thread confirmer([&] {
        std::this_thread::sleep_for(5ms);
        std::unique_lock lock(timedMutex);
        workerEntered = true;
        cv.notify_all();            // 尝试唤醒等待线程检查 worker 状态
    });

    std::unique_lock<std::timed_mutex> lock(timedMutex);
    auto status = cv.wait_for(lock, 10ms, [&] { return dataReady; });
    if (!status) {
        // 10ms 内 dataReady 仍为 false，防止虚假唤醒需继续等待
        status = cv.wait_for(lock, 20ms, [&] { return dataReady; });
    }

    lock.unlock();
    producer.join();
    confirmer.join();

    EXPECT_TRUE(status);
    EXPECT_TRUE(dataReady);
    EXPECT_TRUE(workerEntered);
}

//------------------------------------------------------------------------------
// 3) 任务队列场景：共享读锁支持多线程 peek，写线程推送任务并通知。
//------------------------------------------------------------------------------
class SharedTaskQueue {
public:
    void Push(int value) {
        {
            std::unique_lock lock(mutex_);
            queue_.push(value);
        }
        cv_.notify_one();  // 先释放锁后通知，避免唤醒线程立即阻塞
    }

    int Pop() {
        std::unique_lock lock(mutex_);
        cv_.wait(lock, [&] { return stopped_ || !queue_.empty(); });
        if (queue_.empty()) {
            return -1;
        }
        int value = queue_.front();
        queue_.pop();
        return value;
    }

    int PeekSizeShared() {
        // shared_lock 允许多个读者同时查看队列状态
        std::shared_lock lock(mutex_);
        return static_cast<int>(queue_.size());
    }

    void Stop() {
        {
            std::unique_lock lock(mutex_);
            stopped_ = true;
        }
        cv_.notify_all();
    }

private:
    std::condition_variable_any cv_;
    std::shared_mutex mutex_;
    std::queue<int> queue_;
    bool stopped_ = false;
};

TEST(ConditionVariableAnyUsageTest, SharedMutexQueueProducerConsumer) {
    SharedTaskQueue queue;

    std::thread producer([&] {
        for (int i = 0; i < 3; ++i) {
            queue.Push(i);
            std::this_thread::sleep_for(2ms);
        }
        queue.Stop();
    });

    std::vector<int> results;
    std::thread consumer([&] {
        while (true) {
            int value = queue.Pop();
            if (value < 0) {
                break;
            }
            results.push_back(value);
        }
    });

    producer.join();
    consumer.join();

    EXPECT_EQ(results.size(), 3u);
    EXPECT_EQ(results[0], 0);
    EXPECT_GE(queue.PeekSizeShared(), 0);
}

//------------------------------------------------------------------------------
// 4) 自定义 BasicLockable：证明 condition_variable_any 可与任意符合接口的锁协作。
//------------------------------------------------------------------------------
class SimpleSpinLock {
public:
    void lock() {
        while (flag_.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
    }

    void unlock() {
        flag_.clear(std::memory_order_release);
    }

private:
    std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
};

TEST(ConditionVariableAnyUsageTest, SupportsCustomBasicLockable) {
    SimpleSpinLock spin;
    std::condition_variable_any cv;
    bool ready = false;

    std::thread producer([&] {
        std::this_thread::sleep_for(5ms);
        std::unique_lock lock(spin);
        ready = true;
        cv.notify_one();
    });

    std::unique_lock lock(spin);
    cv.wait(lock, [&] { return ready; });
    producer.join();
    EXPECT_TRUE(ready);
}